
#ifndef TEMPLET_H
#define TEMPLET_H
#include <string>
#include <vector>
#include <map>
#include "utilfun.h"
#include "freelist.h"

using namespace std;

typedef struct graph_node{
	int row;
	int col;
	int type;
	//type: 0 p, 1 b, 2 c, 3 r, 4 dir, 5 dis, 6 type
	int par;
	int sib;		//number of its brothers
	int id;
	int cluster_id;
	vector<int> child;	//index of children in the tree, child.size()=pos.size()
	vector<int> follow;	//index of children in the graph, follow.size()>=child.size()
}graph_node;


class span_feature
{
public:
	int y_pre;//dependency label
	int y_cur;
	int index;//feature index
	int tpl;
	span_feature()
	{ y_pre=y_cur=-1;index=-1;tpl=-1;}

	span_feature& operator = (const span_feature& v)
	{
		y_pre=v.y_pre;
		y_cur=v.y_cur;
		index = v.index;
		tpl = v.tpl;
		return *this;
	}
} ;

struct sentence_inter{
	vector<int> label;
	vector<vector<span_feature>> word_feas;
	int l;

};


struct sentence_rawin
{
	vector<vector<string> > table;

	vector<int>	   sentence_wordIdx2characterIdxB;
	vector<int>	   sentence_wordIdx2characterIdxE;
	vector<string> sentence_character;

	int size() {return (int)table.size(); }
};

struct tag_item {
	int idx;
	map<string,int> pretagidx;
	vector<string> pretag_vec;
};

class TempleteFea{
public:
	TempleteFea(int x_freq, int ysize);//cols of train file
	~TempleteFea();
	bool load_templet(char *templet_file);

	void generate_feature_candidate(sentence_rawin & table);
	void generate_feature(sentence_rawin & table, vector<vector<string> > &vf);
	void generate_feature(sentence_rawin & table, sentence_inter &vf);

	void generate_feature_candidate_zero(sentence_rawin & table);
	void generate_feature_zero(sentence_rawin & table, vector<vector<string> > &vf);
	void generate_feature_zero(sentence_rawin & table, sentence_inter &vf);


	bool load_model(char *model_file,bool require_features);
	bool write_model(char *model_file,int trink_num=-1);
public:
	int _ysize;
	int _x_freq;
	int _feature_space_cal;
	vector<string> _templet_str;
	bool _zero_order;
	
	bool get_cluster_string(sentence_rawin & table, int cur_pos, vector<string> &s);

	bool get_feature_string_from_cluster( sentence_rawin & table,vector<string> &cluster, int templet_id,
								int cur_pos, vector<string> &s,bool bIndTag = true);

	void construct_templet_graph(vector<string> &templets);

	bool insert_feature(string &fs,int templet_id,string& y_cur,string& y_pre) {
		return insert_feature(fs.c_str(),fs.length(),templet_id,y_cur,y_pre); 
	}
	bool insert_feature(const char* fs,int fs_len,int templet_id,string& y_cur,string& y_pre);
	bool insert_tagpair(string& y_cur,string& y_pre,int& cur_id,int& pre_id);

	vector<vector<int> > _templet_path;
	vector<graph_node> _gnode;
	int _tsize;

	vector<graph_node> _gcluster;

	vector<int> _child_size;
	vector<int> _cluster_id;

	freelist<char> _feature_str;
	int _feature_num;
	map<char *, span_feature, str_cmp> _feature2id;

	map<string,tag_item > _tag2idx;

	int getFeaID(char* fea) { 
		map<char *, span_feature, str_cmp>::iterator iter = _feature2id.find(fea);
		if(iter!=_feature2id.end())
			return iter->second.index;
		else
			return -1;
	}
public:
	int get_label_index(string &label);//shared in train and test
	vector<string> _labels;
};







#endif
